实验二 8086的存储
实验日期:2025/10/23
你可能会问:为什么这个实验的部分内容和上一次实验的前期准备重合了
我只能说我们老师就是这样倒着安排实验的,我也无法理解……
字符串
字符串的存储和普通的数字是一样,都需要进行声明。
STR1 DB 'abcde',0
STR2 DB 'a','b','c','d','e',0
如上,行1和行2的作用是一样的,都是声明了一个Byte类型的数据,其中每个字符以ASCII码的形式被存储到相应地址,顺序相连,和数字类型的数据没有什么不同。运行后的效果如下:

可以注意到,在字符串后还会多存一个0(转化成字符也就是空字符),它的作用与C语言里字符串后的\0字符是一样,都是用来表示字符串在此处结束的。
如果我们想在数据里加上一些其他的ASCII码字符,例如\n(即空行),可以直接在字符串后加上13(因为\n对应的ASCII码是13)。
这种存储字符串的方式只记录了其起始位置,而没有其他信息,如果我们想要记录这个字符串的长度,可以使用$字符进行简单的计算。字符表示当前地址,用它减去字符串的起始位置(当前地址和起始地址均为偏移地址),就得到了字符串的长度(显然包括末尾的空字符)。
STR DB 'abcde',0
LEN EQU $ - STR
MOV AX, LEN
还有一些专门用于字符串操作的指令:
MOVS,用于字符串数据的传送,有MOVSB,MOVSW和MOVSD三个变种,分别表示字节类型,字类型和双字类型的字符串数据传送。
输出到屏幕
在内存地址空间中,B8000H~BFFFFH共32kb的范围是显示缓冲区,写入这个范围的数据会直接以字符的形式被打印到屏幕上,不需要我们自行说明什么时候打印以及打印哪里的数据。
MOV AX, 0B800H
MOV ES, AX
MOV SI, 0
MOV ES:[SI], 65
例如,上面的代码会将65存储到0B8000H地址上,因此运行程序后,屏幕上会打印65所对应的字符,也就是A。
每一个字符后的Byte类型地址内的数据表示的是前面这个字符的颜色,这个字节称为属性字节。属性字节的8位每一位都有不同的含义:从左往右数,第0位表示是否闪烁,第1~3位分别表示背景色的R、G、B,第4位表示是否高亮,第5~7位分别表示前景色的R、G、B。例如如下代码:
MOV AX, 0B800H
MOV ES, AX
MOV SI, 0
MOV ES:[SI], 65
INC SI
MOV ES:[SI], 01110100B ;白色背景+红色前景
INC SI
MOV ES:[SI], 66
INC SI
MOV ES:[SI], 00001010B ;黑色背景+高亮+绿色前景

程序编写
此次实验要求:任意选取一段存储单元,存进任意一串字符,并且调用DOS功能,给背景和字符着色,最后在显示屏上显示出来。
以下代码可以实现对应功能:
ASSUME DS:DATA, CS:CODE
DATA SEGMENT
DB 'Hello World!',0
DATA ENDS
CODE SEGMENT
START:
MOV AX, 0B800H
MOV DS, AX
MOV SI, DATA
MOV ES, SI
MOV SI, 0
MOV CX, 0
SHOW_ONE_WORD: ;打印单个字符
CMP SI, 5 ;前五个字符红色,后面的青色
JG BLACK_AND_BLUE
JLE BLACK_AND_RED
LOOP SHOW_ONE_WORD
BLACK_AND_RED:
MOV AL, ES:[SI] ;把字符读入AL
INC SI
MOV AH, 0CH ;设定字符颜色
MOV CL, AL ;如果读到空字符就跳出
JCXZ OVER
MOV DS:[BX], AX
ADD BX, 2
JMP SHOW_ONE_WORD
BLACK_AND_BLUE:
MOV AL, ES:[SI]
INC SI
MOV AH, 0BH
MOV CL, AL
JCXZ OVER
MOV DS:[BX], AX
ADD BX, 2
JMP SHOW_ONE_WORD
OVER:
MOV AX, 4C00H
INT 21H
CODE ENDS
END START
程序运行效果如下图:
